class Route < ActiveRecord::Base

  has_many :route_instances
  has_many :route_recurrence_rules
  has_many :stops

  validates_presence_of :name
  validate :has_stops
  
  def new_stop_attributes=(stop_attributes)
    stop_attributes.each { |attributes|
      stops.build(attributes)
    }
  end
  
  def couriers
    (route_instances.map { |x| x.courier } +
     route_recurrence_rules.map {|x| x.courier }).uniq
  end
  
  # TEST
  # returns the next n route_instances referencing this route and assigned
  # to the courier with the given courier_id
  def future_route_instances_for(courier_id, n)
    # all route instances that have previously been instantiated and saved
    instances = RouteInstance.find_all_by_route_id_and_courier_id(
      id, courier_id, :conditions => ["day >= ?", Date.today]) || []
    existing_dates = instances.map {|x| x.day}

    # generate more instances according to the recurrence rules
    rules = route_recurrence_rules.select {|x|
      # only rules for this courier
      x.courier_id == courier_id
    }.map {|x|
      # get next dates for this rule
      x.next_dates(n + instances.size).select {|y|
        # ignore dates already instantiated and saved
        not existing_dates.member? y
      }.map {|y|
        # build route instances for each date
        ri = route_instances.build(:day => y, :courier_id => courier_id)
        # use this route's stops field as a template for the route_instance's stop_instances
        stops.each {|stop|
          h = stop.attributes
          # drop stop attributes that shouldn't be copied
          ['id', 'created_at', 'updated_at', 'route_id'].each {|attr|
            h.delete attr
          }
          # add pointer back to generating stop instance
          h['stop_id'] = stop.id
          # actually build the stop instance and associate with this route instance
          ri.stop_instances.build(h)
        }
        # map returns a list of route_instances
        ri
      }
    }.flatten
    
    # return the first n route_instnaces in the union of the existing and generated instances
    (instances + rules).sort {|x,y| x.day <=> y.day}[0...n]
  end
  
private

  def has_stops
    errors.add(:stops, "can not be empty") unless stops.size > 0
  end

end
